package org.springframework.beans.factory.support;

import org.apache.commons.logging.Log;
import org.springframework.beans.*;
import org.springframework.beans.factory.*;
import org.springframework.beans.factory.config.*;
import org.springframework.core.*;
import org.springframework.lang.Nullable;
import org.springframework.util.*;
import org.springframework.util.ReflectionUtils.MethodCallback;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Supplier;

/**
 * Abstract bean factory superclass that implements default bean creation,
 * with the full capabilities specified by the {@link RootBeanDefinition} class.
 * Implements the {@link org.springframework.beans.factory.config.AutowireCapableBeanFactory}
 * interface in addition to AbstractBeanFactory's {@link #createBean} method.
 *
 * <p>Provides bean creation (with constructor resolution), property population,
 * wiring (including autowiring), and initialization. Handles runtime bean
 * references, resolves managed collections, calls initialization methods, etc.
 * Supports autowiring constructors, properties by name, and properties by type.
 *
 * <p>The main template method to be implemented by subclasses is
 * {@link #resolveDependency(DependencyDescriptor, String, Set, TypeConverter)},
 * used for autowiring by type. In case of a factory which is capable of searching
 * its bean definitions, matching beans will typically be implemented through such
 * a search. For other factory styles, simplified matching algorithms can be implemented.
 *
 * <p>Note that this class does <i>not</i> assume or implement bean definition
 * registry capabilities. See {@link DefaultListableBeanFactory} for an implementation
 * of the {@link org.springframework.beans.factory.ListableBeanFactory} and
 * {@link BeanDefinitionRegistry} interfaces, which represent the API and SPI
 * view of such a factory, respectively.
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @author Rob Harrop
 * @author Mark Fisher
 * @author Costin Leau
 * @author Chris Beams
 * @author Sam Brannen
 * @author Phillip Webb
 * @see RootBeanDefinition
 * @see DefaultListableBeanFactory
 * @see BeanDefinitionRegistry
 * @since 13.02.2004
 */
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {

    /** Strategy for creating bean instances. */
    private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();

    /** Resolver strategy for method parameter names. */
    @Nullable
    private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();

    /** Whether to automatically try to resolve circular references between beans. */
    private boolean allowCircularReferences = true;

    /**
     * Whether to resort to injecting a raw bean instance in case of circular reference,
     * even if the injected bean eventually got wrapped.
     */
    private boolean allowRawInjectionDespiteWrapping = false;

    /**
     * Dependency types to ignore on dependency check and autowire, as Set of
     * Class objects: for example, String. Default is none.
     */
    private final Set<Class<?>> ignoredDependencyTypes = new HashSet<>();

    /**
     * Dependency interfaces to ignore on dependency check and autowire, as Set of
     * Class objects. By default, only the BeanFactory interface is ignored.
     */
    private final Set<Class<?>> ignoredDependencyInterfaces = new HashSet<>();

    /**
     * The name of the currently created bean, for implicit dependency registration
     * on getBean etc invocations triggered from a user-specified Supplier callback.
     */
    private final NamedThreadLocal<String> currentlyCreatedBean = new NamedThreadLocal<>("Currently created bean");

    /** Cache of unfinished FactoryBean instances: FactoryBean name to BeanWrapper. */
    //还未完成创建的包装Bean实例缓存
    private final ConcurrentMap<String, BeanWrapper> factoryBeanInstanceCache = new ConcurrentHashMap<>();

    /** Cache of candidate factory methods per factory class. */
    private final ConcurrentMap<Class<?>, Method[]> factoryMethodCandidateCache = new ConcurrentHashMap<>();

    /** Cache of filtered PropertyDescriptors: bean Class to PropertyDescriptor array. */
    private final ConcurrentMap<Class<?>, PropertyDescriptor[]> filteredPropertyDescriptorsCache =
            new ConcurrentHashMap<>();

    /**
     * Create a new AbstractAutowireCapableBeanFactory.
     */
    public AbstractAutowireCapableBeanFactory() {
        super();
        ignoreDependencyInterface(BeanNameAware.class);
        ignoreDependencyInterface(BeanFactoryAware.class);
        ignoreDependencyInterface(BeanClassLoaderAware.class);
    }

    /**
     * Create a new AbstractAutowireCapableBeanFactory with the given parent.
     * @param parentBeanFactory parent bean factory, or {@code null} if none
     */
    public AbstractAutowireCapableBeanFactory(@Nullable BeanFactory parentBeanFactory) {
        this();
        setParentBeanFactory(parentBeanFactory);
    }

    /**
     * Set the instantiation strategy to use for creating bean instances.
     * Default is CglibSubclassingInstantiationStrategy.
     * @see CglibSubclassingInstantiationStrategy
     */
    public void setInstantiationStrategy(InstantiationStrategy instantiationStrategy) {
        this.instantiationStrategy = instantiationStrategy;
    }

    /**
     * Return the instantiation strategy to use for creating bean instances.
     */
    protected InstantiationStrategy getInstantiationStrategy() {
        return this.instantiationStrategy;
    }

    /**
     * Set the ParameterNameDiscoverer to use for resolving method parameter
     * names if needed (e.g. for constructor names).
     * <p>Default is a {@link DefaultParameterNameDiscoverer}.
     */
    public void setParameterNameDiscoverer(@Nullable ParameterNameDiscoverer parameterNameDiscoverer) {
        this.parameterNameDiscoverer = parameterNameDiscoverer;
    }

    /**
     * Return the ParameterNameDiscoverer to use for resolving method parameter
     * names if needed.
     */
    @Nullable
    protected ParameterNameDiscoverer getParameterNameDiscoverer() {
        return this.parameterNameDiscoverer;
    }

    /**
     * Set whether to allow circular references between beans - and automatically
     * try to resolve them.
     * <p>Note that circular reference resolution means that one of the involved beans
     * will receive a reference to another bean that is not fully initialized yet.
     * This can lead to subtle and not-so-subtle side effects on initialization;
     * it does work fine for many scenarios, though.
     * <p>Default is "true". Turn this off to throw an exception when encountering
     * a circular reference, disallowing them completely.
     * <p><b>NOTE:</b> It is generally recommended to not rely on circular references
     * between your beans. Refactor your application logic to have the two beans
     * involved delegate to a third bean that encapsulates their common logic.
     */
    public void setAllowCircularReferences(boolean allowCircularReferences) {
        this.allowCircularReferences = allowCircularReferences;
    }

    /**
     * Set whether to allow the raw injection of a bean instance into some other
     * bean's property, despite the injected bean eventually getting wrapped
     * (for example, through AOP auto-proxying).
     * <p>This will only be used as a last resort in case of a circular reference
     * that cannot be resolved otherwise: essentially, preferring a raw instance
     * getting injected over a failure of the entire bean wiring process.
     * <p>Default is "false", as of Spring 2.0. Turn this on to allow for non-wrapped
     * raw beans injected into some of your references, which was Spring 1.2's
     * (arguably unclean) default behavior.
     * <p><b>NOTE:</b> It is generally recommended to not rely on circular references
     * between your beans, in particular with auto-proxying involved.
     * @see #setAllowCircularReferences
     */
    public void setAllowRawInjectionDespiteWrapping(boolean allowRawInjectionDespiteWrapping) {
        this.allowRawInjectionDespiteWrapping = allowRawInjectionDespiteWrapping;
    }

    /**
     * Ignore the given dependency type for autowiring:
     * for example, String. Default is none.
     */
    public void ignoreDependencyType(Class<?> type) {
        this.ignoredDependencyTypes.add(type);
    }

    /**
     * Ignore the given dependency interface for autowiring.
     * <p>This will typically be used by application contexts to register
     * dependencies that are resolved in other ways, like BeanFactory through
     * BeanFactoryAware or ApplicationContext through ApplicationContextAware.
     * <p>By default, only the BeanFactoryAware interface is ignored.
     * For further types to ignore, invoke this method for each type.
     * @see org.springframework.beans.factory.BeanFactoryAware
     * @see org.springframework.context.ApplicationContextAware
     */
    public void ignoreDependencyInterface(Class<?> ifc) {
        this.ignoredDependencyInterfaces.add(ifc);
    }

    @Override
    public void copyConfigurationFrom(ConfigurableBeanFactory otherFactory) {
        super.copyConfigurationFrom(otherFactory);
        if(otherFactory instanceof AbstractAutowireCapableBeanFactory){
            AbstractAutowireCapableBeanFactory otherAutowireFactory = (AbstractAutowireCapableBeanFactory)otherFactory;
            this.instantiationStrategy = otherAutowireFactory.instantiationStrategy;
            this.allowCircularReferences = otherAutowireFactory.allowCircularReferences;
            this.ignoredDependencyTypes.addAll(otherAutowireFactory.ignoredDependencyTypes);
            this.ignoredDependencyInterfaces.addAll(otherAutowireFactory.ignoredDependencyInterfaces);
        }
    }

    //-------------------------------------------------------------------------
    // Typical methods for creating and populating external bean instances
    //-------------------------------------------------------------------------

    @Override
    @SuppressWarnings("unchecked")
    public <T> T createBean(Class<T> beanClass) throws BeansException {
        // Use prototype bean definition, to avoid registering bean as dependent bean.
        RootBeanDefinition bd = new RootBeanDefinition(beanClass);
        bd.setScope(SCOPE_PROTOTYPE);
        bd.allowCaching = ClassUtils.isCacheSafe(beanClass, getBeanClassLoader());
        return (T)createBean(beanClass.getName(), bd, null);
    }

    @Override
    public void autowireBean(Object existingBean) {
        // Use non-singleton bean definition, to avoid registering bean as dependent bean.
        RootBeanDefinition bd = new RootBeanDefinition(ClassUtils.getUserClass(existingBean));
        bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
        bd.allowCaching = ClassUtils.isCacheSafe(bd.getBeanClass(), getBeanClassLoader());
        BeanWrapper bw = new BeanWrapperImpl(existingBean);
        initBeanWrapper(bw);
        populateBean(bd.getBeanClass().getName(), bd, bw);
    }

    @Override
    public Object configureBean(Object existingBean, String beanName) throws BeansException {
        markBeanAsCreated(beanName);
        BeanDefinition mbd = getMergedBeanDefinition(beanName);
        RootBeanDefinition bd = null;
        if(mbd instanceof RootBeanDefinition){
            RootBeanDefinition rbd = (RootBeanDefinition)mbd;
            bd = (rbd.isPrototype()?rbd:rbd.cloneBeanDefinition());
        }
        if(bd == null){
            bd = new RootBeanDefinition(mbd);
        }
        if(!bd.isPrototype()){
            bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
            bd.allowCaching = ClassUtils.isCacheSafe(ClassUtils.getUserClass(existingBean), getBeanClassLoader());
        }
        BeanWrapper bw = new BeanWrapperImpl(existingBean);
        initBeanWrapper(bw);
        populateBean(beanName, bd, bw);
        return initializeBean(beanName, existingBean, bd);
    }

    //-------------------------------------------------------------------------
    // Specialized methods for fine-grained control over the bean lifecycle
    //-------------------------------------------------------------------------

    @Override
    public Object createBean(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException {
        // Use non-singleton bean definition, to avoid registering bean as dependent bean.
        RootBeanDefinition bd = new RootBeanDefinition(beanClass, autowireMode, dependencyCheck);
        bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
        return createBean(beanClass.getName(), bd, null);
    }

    @Override
    public Object autowire(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException {
        // Use non-singleton bean definition, to avoid registering bean as dependent bean.
        final RootBeanDefinition bd = new RootBeanDefinition(beanClass, autowireMode, dependencyCheck);
        bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
        if(bd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR){
            return autowireConstructor(beanClass.getName(), bd, null, null).getWrappedInstance();
        }else{
            Object bean;
            final BeanFactory parent = this;
            if(System.getSecurityManager() != null){
                bean = AccessController.doPrivileged((PrivilegedAction<Object>)() -> getInstantiationStrategy().instantiate(bd, null, parent), getAccessControlContext());
            }else{
                bean = getInstantiationStrategy().instantiate(bd, null, parent);
            }
            populateBean(beanClass.getName(), bd, new BeanWrapperImpl(bean));
            return bean;
        }
    }

    @Override
    public void autowireBeanProperties(Object existingBean, int autowireMode, boolean dependencyCheck) throws BeansException {

        if(autowireMode == AUTOWIRE_CONSTRUCTOR){
            throw new IllegalArgumentException("AUTOWIRE_CONSTRUCTOR not supported for existing bean instance");
        }
        // Use non-singleton bean definition, to avoid registering bean as dependent bean.
        RootBeanDefinition bd = new RootBeanDefinition(ClassUtils.getUserClass(existingBean), autowireMode,
                dependencyCheck);
        bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
        BeanWrapper bw = new BeanWrapperImpl(existingBean);
        initBeanWrapper(bw);
        populateBean(bd.getBeanClass().getName(), bd, bw);
    }

    @Override
    public void applyBeanPropertyValues(Object existingBean, String beanName) throws BeansException {
        markBeanAsCreated(beanName);
        BeanDefinition bd = getMergedBeanDefinition(beanName);
        BeanWrapper bw = new BeanWrapperImpl(existingBean);
        initBeanWrapper(bw);
        applyPropertyValues(beanName, bd, bw, bd.getPropertyValues());
    }

    @Override
    public Object initializeBean(Object existingBean, String beanName) {
        return initializeBean(beanName, existingBean, null);
    }

    @Override
    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {

        Object result = existingBean;
        for(BeanPostProcessor processor: getBeanPostProcessors()){
            Object current = processor.postProcessBeforeInitialization(result, beanName);
            if(current == null){
                return result;
            }
            result = current;
        }
        return result;
    }

    @Override
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {

        Object result = existingBean;
        for(BeanPostProcessor processor: getBeanPostProcessors()){
            Object current = processor.postProcessAfterInitialization(result, beanName);
            if(current == null){
                return result;
            }
            result = current;
        }
        return result;
    }

    @Override
    public void destroyBean(Object existingBean) {
        new DisposableBeanAdapter(existingBean, getBeanPostProcessors(), getAccessControlContext()).destroy();
    }

    //-------------------------------------------------------------------------
    // Delegate methods for resolving injection points
    //-------------------------------------------------------------------------

    @Override
    public Object resolveBeanByName(String name, DependencyDescriptor descriptor) {
        InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
        try{
            return getBean(name, descriptor.getDependencyType());
        }finally{
            ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
        }
    }

    @Override
    @Nullable
    public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName) throws BeansException {
        return resolveDependency(descriptor, requestingBeanName, null, null);
    }

    //---------------------------------------------------------------------
    // Implementation of relevant AbstractBeanFactory template methods
    //---------------------------------------------------------------------

    /**
     * Central method of this class: creates a bean instance,
     * populates the bean instance, applies post-processors, etc.
     * @see #doCreateBean
     */
    @Override
    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {

        if(logger.isTraceEnabled()){
            logger.trace("Creating instance of bean '" + beanName + "'");
        }
        RootBeanDefinition mbdToUse = mbd;

        // Make sure bean class is actually resolved at this point, and
        // clone the bean definition in case of a dynamically resolved Class
        // which cannot be stored in the shared merged bean definition.
        //判断需要创建的Bean是否可以实例化，即是否可以通过当前的类加载器加载
        Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
        if(resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null){
            //克隆一份BeanDefinition，用来设置上加载出来的class对象
            //之所以后续用该副本操作，是因为不希望将解析的class绑定到缓存里的BeanDefinition
            //因为class有可能是每次都需要动态解析出来的
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }

        // Prepare method overrides.
        //校验和准备Bean中的方法覆盖
        try{
            mbdToUse.prepareMethodOverrides();
        }catch(BeanDefinitionValidationException ex){
            throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method"
                    + " overrides failed", ex);
        }

        try{
            // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
            //如果Bean配置了初始化前和初始化后的处理器，则试图返回一个需要创建Bean的代理对象
            //resolveBeforeInstantiation只是针对有自定义的targetsource，
            // 因为自定义的targetsource不是spring的bean那么肯定不需要进行后续的一系列的实例化,初始化。
            // 所以可以在resolveBeforeInstantiation直接进行proxy
            Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
            if(bean != null){
                return bean;
            }
        }catch(Throwable ex){
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before "
                    + "instantiation of bean failed", ex);
        }

        try{
            //创建Bean的入口
            Object beanInstance = doCreateBean(beanName, mbdToUse, args);
            if(logger.isTraceEnabled()){
                logger.trace("Finished creating instance of bean '" + beanName + "'");
            }
            return beanInstance;
        }catch(BeanCreationException | ImplicitlyAppearedSingletonException ex){
            // A previously detected exception with proper bean creation context already,
            // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
            throw ex;
        }catch(Throwable ex){
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during"
                    + " bean creation", ex);
        }
    }

    /**
     * Actually create the specified bean. Pre-creation processing has already happened
     * at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.
     * <p>Differentiates between default bean instantiation, use of a
     * factory method, and autowiring a constructor.
     * @param beanName the name of the bean
     * @param mbd      the merged bean definition for the bean
     * @param args     explicit arguments to use for constructor or factory method invocation
     * @return a new instance of the bean
     * @throws BeanCreationException if the bean could not be created
     * @see #instantiateBean
     * @see #instantiateUsingFactoryMethod
     * @see #autowireConstructor
     */
    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {

        // Instantiate the bean.
        //bean实例包装类
        BeanWrapper instanceWrapper = null;
        if(mbd.isSingleton()){
            //从未完成创建的包装Bean缓存中清理并获取相关中的包装Bean实例，毕竟是单例的，只能存一份
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if(instanceWrapper == null){
            //创建bean的时候，这里创建bean的实例有三种方法
            //1.工厂方法创建
            //2.构造方法的方式注入
            //3.无参构造方法注入
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        //获取被包装的Bean，后续对bean的改动相当于对Wrapper的改动，反之依然
        final Object bean = instanceWrapper.getWrappedInstance();
        //获取实例化对象的类型
        Class<?> beanType = instanceWrapper.getWrappedClass();
        if(beanType != NullBean.class){
            mbd.resolvedTargetType = beanType;
        }

        // Allow post-processors to modify the merged bean definition.
        //调用BeanDefinition属性合并完成后的BeanPostProcessor后置处理器
        synchronized(mbd.postProcessingLock){
            if(!mbd.postProcessed){
                try{
                    //被@Autowired、@Value标记的属性在这里获取
                    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                }catch(Throwable ex){
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of "
                            + "merged bean definition failed", ex);
                }
                mbd.postProcessed = true;
            }
        }

        // Eagerly cache singletons to be able to resolve circular references
        // even when triggered by lifecycle interfaces like BeanFactoryAware.
        //向容器中缓存单例模式的Bean对象，以防循环引用
        //判断是否是早期引用的bean，如果是，则允许其提前暴露引用
        //这里判断的逻辑主要有三个：
        //1.是否为单例
        //2.是否允许循环引用
        //3.是否是在创建中的bean
        boolean earlySingletonExposure = (mbd.isSingleton()
                && this.allowCircularReferences
                && isSingletonCurrentlyInCreation(beanName));
        if(earlySingletonExposure){
            if(logger.isTraceEnabled()){
                logger.trace("Eagerly caching bean '"
                        + beanName
                        + "' to allow for resolving potential circular references");
            }
            //这里是一个匿名内部类，为了防止循环引用，尽早持有对象的引用
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }

        // Initialize the bean instance.
        //Bean对象的初始化，依赖注入在此触发
        //这个exposedObject在初始化完成之后返回作为依赖注入完成后的Bean
        Object exposedObject = bean;
        try{
            //填充bean实例的属性
            populateBean(beanName, mbd, instanceWrapper);

            //初始化bean，过程如下：
            //1：判断是否实现了BeanNameAware，BeanClassLoaderAware，
            //   BeanFactoryAware方法，如果有，则设置相关的属性
            //2: 调用bean初始化的前置（BeanPostProcessor）操作
            //3: 执行初始化的方法。
            //	如果有initializingBean，则调用afterPropertiesSet
            //	如果有InitMethod，则调用初始方法
            //4: 调用bean初始化的后置（BeanPostProcessor）操作
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }catch(Throwable ex){
            if(ex instanceof BeanCreationException && beanName.equals(((BeanCreationException)ex).getBeanName())){
                throw (BeanCreationException)ex;
            }else{
                throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean "
                        + "failed", ex);
            }
        }
        //若允许循环依赖，则解决相关的循环依赖
        if(earlySingletonExposure){
            //获取指定名称的已注册的单例模式Bean对象
            Object earlySingletonReference = getSingleton(beanName, false);
            if(earlySingletonReference != null){
                //如果经过initializeBean执行后返回的bean还是同一个（不是代理对象实例,即没有被增强）
                if(exposedObject == bean){
                    // 确保根据名称获取到的的已注册的Bean和正在实例化的Bean是同一个
                    exposedObject = earlySingletonReference;
                }
                //如果上面的if没通过，则表明引用的bean和注入的bean不一致，则需要看看依赖于此Bean的先前是否已经注入了不完善的Bean
                // allowRawInjectionDespiteWrapping 标注是否允许此Bean的原始类型被注入到其它Bean里面，
                // 即使自己最终会被包装（代理）
                // dependentBeanMap记录着每个依赖于此Bean的Bean实例集合
                //当发生循环引用时不允许新创建实例对象
                else if(!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)){
                    String[] dependentBeans = getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                    //获取依赖于当前Bean的Bean实例
                    for(String dependentBean: dependentBeans){
                        //移除掉只是用来进行类型检查的单例Bean
                        if(!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)){
                            actualDependentBeans.add(dependentBean);
                        }
                    }
                    /**
                     * 因为bean创建后其所依赖的bean一定是已经创建的
                     * actualDependentBeans不为空则表示当前bean创建后其依赖的bean却没有全部创建完，也就是说存在循环依赖
                     */
                    if(!actualDependentBeans.isEmpty()){
                        throw new BeanCurrentlyInCreationException(beanName, "Bean with name '"
                                + beanName
                                + "' has been injected into other beans ["
                                + StringUtils.collectionToCommaDelimitedString(actualDependentBeans)
                                + "] in its raw version as part of a circular reference, but has eventually been "
                                + "wrapped. This means that said other beans do not use the final version of the "
                                + "bean. This is often the result of over-eager type matching - consider using "
                                + "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                    }
                }
            }
        }

        // Register bean as disposable.
        try{
            //注册Bean的销毁逻辑
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
        }catch(BeanDefinitionValidationException ex){
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature",
                    ex);
        }

        return exposedObject;
    }

    @Override
    @Nullable
    protected Class<?> predictBeanType(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {
        Class<?> targetType = determineTargetType(beanName, mbd, typesToMatch);
        // Apply SmartInstantiationAwareBeanPostProcessors to predict the
        // eventual type after a before-instantiation shortcut.
        if(targetType != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()){
            boolean matchingOnlyFactoryBean = typesToMatch.length == 1 && typesToMatch[0] == FactoryBean.class;
            for(BeanPostProcessor bp: getBeanPostProcessors()){
                if(bp instanceof SmartInstantiationAwareBeanPostProcessor){
                    SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor)bp;
                    Class<?> predicted = ibp.predictBeanType(targetType, beanName);
                    if(predicted != null && (!matchingOnlyFactoryBean
                            || FactoryBean.class.isAssignableFrom(predicted))){
                        return predicted;
                    }
                }
            }
        }
        return targetType;
    }

    /**
     * Determine the target type for the given bean definition.
     * @param beanName     the name of the bean (for error handling purposes)
     * @param mbd          the merged bean definition for the bean
     * @param typesToMatch the types to match in case of internal type matching purposes
     *                     (also signals that the returned {@code Class} will never be exposed to application code)
     * @return the type for the bean if determinable, or {@code null} otherwise
     */
    @Nullable
    protected Class<?> determineTargetType(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {
        Class<?> targetType = mbd.getTargetType();
        if(targetType == null){
            targetType = (mbd.getFactoryMethodName()
                                  != null?getTypeForFactoryMethod(beanName, mbd, typesToMatch):resolveBeanClass(mbd,
                    beanName, typesToMatch));
            if(ObjectUtils.isEmpty(typesToMatch) || getTempClassLoader() == null){
                mbd.resolvedTargetType = targetType;
            }
        }
        return targetType;
    }

    /**
     * Determine the target type for the given bean definition which is based on
     * a factory method. Only called if there is no singleton instance registered
     * for the target bean already.
     * <p>This implementation determines the type matching {@link #createBean}'s
     * different creation strategies. As far as possible, we'll perform static
     * type checking to avoid creation of the target bean.
     * @param beanName     the name of the bean (for error handling purposes)
     * @param mbd          the merged bean definition for the bean
     * @param typesToMatch the types to match in case of internal type matching purposes
     *                     (also signals that the returned {@code Class} will never be exposed to application code)
     * @return the type for the bean if determinable, or {@code null} otherwise
     * @see #createBean
     */
    @Nullable
    protected Class<?> getTypeForFactoryMethod(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {
        ResolvableType cachedReturnType = mbd.factoryMethodReturnType;
        if(cachedReturnType != null){
            return cachedReturnType.resolve();
        }

        Class<?> commonType = null;
        Method uniqueCandidate = mbd.factoryMethodToIntrospect;

        if(uniqueCandidate == null){
            Class<?> factoryClass;
            boolean isStatic = true;

            String factoryBeanName = mbd.getFactoryBeanName();
            if(factoryBeanName != null){
                if(factoryBeanName.equals(beanName)){
                    throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName, "factory-bean "
                            + "reference points back to the same bean definition");
                }
                // Check declared factory method return type on factory class.
                factoryClass = getType(factoryBeanName);
                isStatic = false;
            }else{
                // Check declared factory method return type on bean class.
                factoryClass = resolveBeanClass(mbd, beanName, typesToMatch);
            }

            if(factoryClass == null){
                return null;
            }
            factoryClass = ClassUtils.getUserClass(factoryClass);

            // If all factory methods have the same return type, return that type.
            // Can't clearly figure out exact method due to type converting / autowiring!
            int minNrOfArgs = (mbd.hasConstructorArgumentValues()?mbd.getConstructorArgumentValues()
                                                                     .getArgumentCount():0);
            Method[] candidates = this.factoryMethodCandidateCache.computeIfAbsent(factoryClass,
                    clazz -> ReflectionUtils
                    .getUniqueDeclaredMethods(clazz, ReflectionUtils.USER_DECLARED_METHODS));

            for(Method candidate: candidates){
                if(Modifier.isStatic(candidate.getModifiers()) == isStatic
                        && mbd.isFactoryMethod(candidate)
                        && candidate.getParameterCount() >= minNrOfArgs){
                    // Declared type variables to inspect?
                    if(candidate.getTypeParameters().length > 0){
                        try{
                            // Fully resolve parameter names and argument values.
                            Class<?>[] paramTypes = candidate.getParameterTypes();
                            String[] paramNames = null;
                            ParameterNameDiscoverer pnd = getParameterNameDiscoverer();
                            if(pnd != null){
                                paramNames = pnd.getParameterNames(candidate);
                            }
                            ConstructorArgumentValues cav = mbd.getConstructorArgumentValues();
                            Set<ConstructorArgumentValues.ValueHolder> usedValueHolders =
                                    new HashSet<>(paramTypes.length);
                            Object[] args = new Object[paramTypes.length];
                            for(int i = 0; i < args.length; i++){
                                ConstructorArgumentValues.ValueHolder valueHolder = cav.getArgumentValue(i,
                                        paramTypes[i], (
                                        paramNames
                                                != null?paramNames[i]:null), usedValueHolders);
                                if(valueHolder == null){
                                    valueHolder = cav.getGenericArgumentValue(null, null, usedValueHolders);
                                }
                                if(valueHolder != null){
                                    args[i] = valueHolder.getValue();
                                    usedValueHolders.add(valueHolder);
                                }
                            }
                            Class<?> returnType = AutowireUtils.resolveReturnTypeForFactoryMethod(candidate, args,
                                    getBeanClassLoader());
                            uniqueCandidate = (commonType == null
                                                       && returnType == candidate.getReturnType()?candidate:null);
                            commonType = ClassUtils.determineCommonAncestor(returnType, commonType);
                            if(commonType == null){
                                // Ambiguous return types found: return null to indicate "not determinable".
                                return null;
                            }
                        }catch(Throwable ex){
                            if(logger.isDebugEnabled()){
                                logger.debug("Failed to resolve generic return type for factory method: " + ex);
                            }
                        }
                    }else{
                        uniqueCandidate = (commonType == null?candidate:null);
                        commonType = ClassUtils.determineCommonAncestor(candidate.getReturnType(), commonType);
                        if(commonType == null){
                            // Ambiguous return types found: return null to indicate "not determinable".
                            return null;
                        }
                    }
                }
            }

            mbd.factoryMethodToIntrospect = uniqueCandidate;
            if(commonType == null){
                return null;
            }
        }

        // Common return type found: all factory methods return same type. For a non-parameterized
        // unique candidate, cache the full type declaration context of the target factory method.
        cachedReturnType = (uniqueCandidate
                                    != null?ResolvableType.forMethodReturnType(uniqueCandidate):
                            ResolvableType.forClass(commonType));
        mbd.factoryMethodReturnType = cachedReturnType;
        return cachedReturnType.resolve();
    }

    /**
     * This implementation attempts to query the FactoryBean's generic parameter metadata
     * if present to determine the object type. If not present, i.e. the FactoryBean is
     * declared as a raw type, checks the FactoryBean's {@code getObjectType} method
     * on a plain instance of the FactoryBean, without bean properties applied yet.
     * If this doesn't return a type yet, and {@code allowInit} is {@code true} a
     * full creation of the FactoryBean is used as fallback (through delegation to the
     * superclass's implementation).
     * <p>The shortcut check for a FactoryBean is only applied in case of a singleton
     * FactoryBean. If the FactoryBean instance itself is not kept as singleton,
     * it will be fully created to check the type of its exposed object.
     */
    @Override
    protected ResolvableType getTypeForFactoryBean(String beanName, RootBeanDefinition mbd, boolean allowInit) {
        // Check if the bean definition itself has defined the type with an attribute
        ResolvableType result = getTypeForFactoryBeanFromAttributes(mbd);
        if(result != ResolvableType.NONE){
            return result;
        }

        ResolvableType beanType = (mbd.hasBeanClass()?ResolvableType.forClass(mbd.getBeanClass()):ResolvableType.NONE);

        // For instance supplied beans try the target type and bean class
        if(mbd.getInstanceSupplier() != null){
            result = getFactoryBeanGeneric(mbd.targetType);
            if(result.resolve() != null){
                return result;
            }
            result = getFactoryBeanGeneric(beanType);
            if(result.resolve() != null){
                return result;
            }
        }

        // Consider factory methods
        String factoryBeanName = mbd.getFactoryBeanName();
        String factoryMethodName = mbd.getFactoryMethodName();

        // Scan the factory bean methods
        if(factoryBeanName != null){
            if(factoryMethodName != null){
                // Try to obtain the FactoryBean's object type from its factory method
                // declaration without instantiating the containing bean at all.
                BeanDefinition factoryBeanDefinition = getBeanDefinition(factoryBeanName);
                Class<?> factoryBeanClass;
                if(factoryBeanDefinition instanceof AbstractBeanDefinition
                        && ((AbstractBeanDefinition)factoryBeanDefinition).hasBeanClass()){
                    factoryBeanClass = ((AbstractBeanDefinition)factoryBeanDefinition).getBeanClass();
                }else{
                    RootBeanDefinition fbmbd = getMergedBeanDefinition(factoryBeanName, factoryBeanDefinition);
                    factoryBeanClass = determineTargetType(factoryBeanName, fbmbd);
                }
                if(factoryBeanClass != null){
                    result = getTypeForFactoryBeanFromMethod(factoryBeanClass, factoryMethodName);
                    if(result.resolve() != null){
                        return result;
                    }
                }
            }
            // If not resolvable above and the referenced factory bean doesn't exist yet,
            // exit here - we don't want to force the creation of another bean just to
            // obtain a FactoryBean's object type...
            if(!isBeanEligibleForMetadataCaching(factoryBeanName)){
                return ResolvableType.NONE;
            }
        }

        // If we're allowed, we can create the factory bean and call getObjectType() early
        if(allowInit){
            FactoryBean<?> factoryBean = (mbd.isSingleton()?getSingletonFactoryBeanForTypeCheck(beanName, mbd):
                                          getNonSingletonFactoryBeanForTypeCheck(beanName, mbd));
            if(factoryBean != null){
                // Try to obtain the FactoryBean's object type from this early stage of the instance.
                Class<?> type = getTypeForFactoryBean(factoryBean);
                if(type != null){
                    return ResolvableType.forClass(type);
                }
                // No type found for shortcut FactoryBean instance:
                // fall back to full creation of the FactoryBean instance.
                return super.getTypeForFactoryBean(beanName, mbd, true);
            }
        }

        if(factoryBeanName == null && mbd.hasBeanClass() && factoryMethodName != null){
            // No early bean instantiation possible: determine FactoryBean's type from
            // static factory method signature or from class inheritance hierarchy...
            return getTypeForFactoryBeanFromMethod(mbd.getBeanClass(), factoryMethodName);
        }
        result = getFactoryBeanGeneric(beanType);
        if(result.resolve() != null){
            return result;
        }
        return ResolvableType.NONE;
    }

    private ResolvableType getFactoryBeanGeneric(@Nullable ResolvableType type) {
        if(type == null){
            return ResolvableType.NONE;
        }
        return type.as(FactoryBean.class).getGeneric();
    }

    /**
     * Introspect the factory method signatures on the given bean class,
     * trying to find a common {@code FactoryBean} object type declared there.
     * @param beanClass         the bean class to find the factory method on
     * @param factoryMethodName the name of the factory method
     * @return the common {@code FactoryBean} object type, or {@code null} if none
     */
    private ResolvableType getTypeForFactoryBeanFromMethod(Class<?> beanClass, String factoryMethodName) {
        // CGLIB subclass methods hide generic parameters; look at the original user class.
        Class<?> factoryBeanClass = ClassUtils.getUserClass(beanClass);
        FactoryBeanMethodTypeFinder finder = new FactoryBeanMethodTypeFinder(factoryMethodName);
        ReflectionUtils.doWithMethods(factoryBeanClass, finder, ReflectionUtils.USER_DECLARED_METHODS);
        return finder.getResult();
    }

    /**
     * This implementation attempts to query the FactoryBean's generic parameter metadata
     * if present to determine the object type. If not present, i.e. the FactoryBean is
     * declared as a raw type, checks the FactoryBean's {@code getObjectType} method
     * on a plain instance of the FactoryBean, without bean properties applied yet.
     * If this doesn't return a type yet, a full creation of the FactoryBean is
     * used as fallback (through delegation to the superclass's implementation).
     * <p>The shortcut check for a FactoryBean is only applied in case of a singleton
     * FactoryBean. If the FactoryBean instance itself is not kept as singleton,
     * it will be fully created to check the type of its exposed object.
     */
    @Override
    @Deprecated
    @Nullable
    protected Class<?> getTypeForFactoryBean(String beanName, RootBeanDefinition mbd) {
        return getTypeForFactoryBean(beanName, mbd, true).resolve();
    }

    /**
     * 这个方法是spring的三级缓存中的其中一环，
     * 当你调用Object earlySingletonReference = getSingleton(beanName, false);时候就会触发，
     * 其实还有一个地方exposedObject = initializeBean(beanName, exposedObject, mbd);
     * 也会触发导致返回一个代理对象
     * Obtain a reference for early access to the specified bean,
     * typically for the purpose of resolving a circular reference.
     * @param beanName the name of the bean (for error handling purposes)
     * @param mbd      the merged bean definition for the bean
     * @param bean     the raw bean instance
     * @return the object to expose as bean reference
     */
    protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
        Object exposedObject = bean;
        if(!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()){
            for(BeanPostProcessor bp: getBeanPostProcessors()){
                //如果是SmartInstantiationAwareBeanPostProcessor类型，就进行处理，
                // 如果没有相关处理内容，就返回默认的实例。
                // 里面的AbstractAutoProxyCreator类是后续AOP的关键
                if(bp instanceof SmartInstantiationAwareBeanPostProcessor){
                    SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor)bp;
                    exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
                }
            }
        }
        return exposedObject;
    }

    //---------------------------------------------------------------------
    // Implementation methods
    //---------------------------------------------------------------------

    /**
     * Obtain a "shortcut" singleton FactoryBean instance to use for a
     * {@code getObjectType()} call, without full initialization of the FactoryBean.
     * @param beanName the name of the bean
     * @param mbd      the bean definition for the bean
     * @return the FactoryBean instance, or {@code null} to indicate
     *         that we couldn't obtain a shortcut FactoryBean instance
     */
    @Nullable
    private FactoryBean<?> getSingletonFactoryBeanForTypeCheck(String beanName, RootBeanDefinition mbd) {
        synchronized(getSingletonMutex()){
            BeanWrapper bw = this.factoryBeanInstanceCache.get(beanName);
            if(bw != null){
                return (FactoryBean<?>)bw.getWrappedInstance();
            }
            Object beanInstance = getSingleton(beanName, false);
            if(beanInstance instanceof FactoryBean){
                return (FactoryBean<?>)beanInstance;
            }
            if(isSingletonCurrentlyInCreation(beanName) || (mbd.getFactoryBeanName() != null
                    && isSingletonCurrentlyInCreation(mbd.getFactoryBeanName()))){
                return null;
            }

            Object instance;
            try{
                // Mark this bean as currently in creation, even if just partially.
                beforeSingletonCreation(beanName);
                // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
                instance = resolveBeforeInstantiation(beanName, mbd);
                if(instance == null){
                    bw = createBeanInstance(beanName, mbd, null);
                    instance = bw.getWrappedInstance();
                }
            }catch(UnsatisfiedDependencyException ex){
                // Don't swallow, probably misconfiguration...
                throw ex;
            }catch(BeanCreationException ex){
                // Instantiation failure, maybe too early...
                if(logger.isDebugEnabled()){
                    logger.debug("Bean creation exception on singleton FactoryBean type check: " + ex);
                }
                onSuppressedException(ex);
                return null;
            }finally{
                // Finished partial creation of this bean.
                afterSingletonCreation(beanName);
            }

            FactoryBean<?> fb = getFactoryBean(beanName, instance);
            if(bw != null){
                this.factoryBeanInstanceCache.put(beanName, bw);
            }
            return fb;
        }
    }

    /**
     * Obtain a "shortcut" non-singleton FactoryBean instance to use for a
     * {@code getObjectType()} call, without full initialization of the FactoryBean.
     * @param beanName the name of the bean
     * @param mbd      the bean definition for the bean
     * @return the FactoryBean instance, or {@code null} to indicate
     *         that we couldn't obtain a shortcut FactoryBean instance
     */
    @Nullable
    private FactoryBean<?> getNonSingletonFactoryBeanForTypeCheck(String beanName, RootBeanDefinition mbd) {
        if(isPrototypeCurrentlyInCreation(beanName)){
            return null;
        }

        Object instance;
        try{
            // Mark this bean as currently in creation, even if just partially.
            beforePrototypeCreation(beanName);
            // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
            instance = resolveBeforeInstantiation(beanName, mbd);
            if(instance == null){
                BeanWrapper bw = createBeanInstance(beanName, mbd, null);
                instance = bw.getWrappedInstance();
            }
        }catch(UnsatisfiedDependencyException ex){
            // Don't swallow, probably misconfiguration...
            throw ex;
        }catch(BeanCreationException ex){
            // Instantiation failure, maybe too early...
            if(logger.isDebugEnabled()){
                logger.debug("Bean creation exception on non-singleton FactoryBean type check: " + ex);
            }
            onSuppressedException(ex);
            return null;
        }finally{
            // Finished partial creation of this bean.
            afterPrototypeCreation(beanName);
        }

        return getFactoryBean(beanName, instance);
    }

    /**
     * Apply MergedBeanDefinitionPostProcessors to the specified bean definition,
     * invoking their {@code postProcessMergedBeanDefinition} methods.
     * @param mbd      the merged bean definition for the bean
     * @param beanType the actual type of the managed bean instance
     * @param beanName the name of the bean
     * @see MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
     */
    protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
        for(BeanPostProcessor bp: getBeanPostProcessors()){
            if(bp instanceof MergedBeanDefinitionPostProcessor){
                MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor)bp;
                //重点关注AutowiredAnnotationBeanPostProcessor，该类会把@Autowired等标记的
                //需要依赖注入的成员变量或者方法实例给记录下来，方便后续populateBean使用
                bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
            }
        }
    }

    /**
     * Apply before-instantiation post-processors, resolving whether there is a
     * before-instantiation shortcut for the specified bean.
     * @param beanName the name of the bean
     * @param mbd      the bean definition for the bean
     * @return the shortcut-determined bean instance, or {@code null} if none
     */
    @Nullable
    protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
        Object bean = null;
        //如果beforeInstantiationResolved还没有设置或者是false（说明还没有需要在实例化前执行的操作）
        if(!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)){
            // Make sure bean class is actually resolved at this point.
            //mbd.isSynthetic()默认是false，
            // 如果注册了InstantiationAwareBeanPostProcessors类型的BeanPostProcessor，
            if(!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()){
                Class<?> targetType = determineTargetType(beanName, mbd);
                if(targetType != null){
                    bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                    if(bean != null){
                        bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                    }
                }
            }
            mbd.beforeInstantiationResolved = (bean != null);
        }
        return bean;
    }

    /**
     * Apply InstantiationAwareBeanPostProcessors to the specified bean definition
     * (by class and name), invoking their {@code postProcessBeforeInstantiation} methods.
     * <p>Any returned object will be used as the bean instead of actually instantiating
     * the target bean. A {@code null} return value from the post-processor will
     * result in the target bean being instantiated.
     * @param beanClass the class of the bean to be instantiated
     * @param beanName  the name of the bean
     * @return the bean object to use instead of a default instance of the target bean, or {@code null}
     * @see InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
     */
    @Nullable
    protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
        for(BeanPostProcessor bp: getBeanPostProcessors()){
            if(bp instanceof InstantiationAwareBeanPostProcessor){
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
                Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
                if(result != null){
                    return result;
                }
            }
        }
        return null;
    }

    /**
     * Create a new instance for the specified bean, using an appropriate instantiation strategy:
     * factory method, constructor autowiring, or simple instantiation.
     * @param beanName the name of the bean
     * @param mbd      the bean definition for the bean
     * @param args     explicit arguments to use for constructor or factory method invocation
     * @return a BeanWrapper for the new instance
     * @see #obtainFromSupplier
     * @see #instantiateUsingFactoryMethod
     * @see #autowireConstructor
     * @see #instantiateBean
     */
    protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
        // Make sure bean class is actually resolved at this point.
        Class<?> beanClass = resolveBeanClass(mbd, beanName);
        //检查是否有权通过反射创建private的Class
        if(beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()){
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "Bean class isn't public, and non-public access not allowed: "
                            + beanClass.getName());
        }
        //使用工厂方法创建实例
        Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
        if(instanceSupplier != null){
            return obtainFromSupplier(instanceSupplier, beanName);
        }
        //factory-method
        // 如果工厂方法不为空，则使用工厂方法初始化策略
        if(mbd.getFactoryMethodName() != null){
            return instantiateUsingFactoryMethod(beanName, mbd, args);
        }

        // Shortcut when re-creating the same bean...
        boolean resolved = false;
        boolean autowireNecessary = false;
        if(args == null){
            synchronized(mbd.constructorArgumentLock){
                // 如果已缓存的解析的构造函数或者工厂方法不为空，则可以利用构造函数解析
                // 因为需要根据参数确认到底使用哪个构造函数
                if(mbd.resolvedConstructorOrFactoryMethod != null){
                    resolved = true;
                    autowireNecessary = mbd.constructorArgumentsResolved;
                }
            }
        }
        if(resolved){
            // 自动注入，调用构造函数自动注入
            if(autowireNecessary){
                return autowireConstructor(beanName, mbd, null, null);
            }else{
                // 使用默认构造函数构造
                return instantiateBean(beanName, mbd);
            }
        }

        // Candidate constructors for autowiring?
        // 使用带参的构造函数进行装配
        Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
        if(ctors != null
                || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR
                || mbd.hasConstructorArgumentValues()
                || !ObjectUtils.isEmpty(args)){
            return autowireConstructor(beanName, mbd, ctors, args);
        }

        // Preferred constructors for default construction?
        ctors = mbd.getPreferredConstructors();
        if(ctors != null){
            return autowireConstructor(beanName, mbd, ctors, null);
        }

        // No special handling: simply use no-arg constructor.
        // 使用默认的构造函数
        return instantiateBean(beanName, mbd);
    }

    /**
     * Obtain a bean instance from the given supplier.
     * @param instanceSupplier the configured supplier
     * @param beanName         the corresponding bean name
     * @return a BeanWrapper for the new instance
     * @see #getObjectForBeanInstance
     * @since 5.0
     */
    protected BeanWrapper obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) {
        Object instance;

        String outerBean = this.currentlyCreatedBean.get();
        this.currentlyCreatedBean.set(beanName);
        try{
            instance = instanceSupplier.get();
        }finally{
            if(outerBean != null){
                this.currentlyCreatedBean.set(outerBean);
            }else{
                this.currentlyCreatedBean.remove();
            }
        }

        if(instance == null){
            instance = new NullBean();
        }
        BeanWrapper bw = new BeanWrapperImpl(instance);
        initBeanWrapper(bw);
        return bw;
    }

    /**
     * Overridden in order to implicitly register the currently created bean as
     * dependent on further beans getting programmatically retrieved during a
     * {@link Supplier} callback.
     * @see #obtainFromSupplier
     * @since 5.0
     */
    @Override
    protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName,
                                              @Nullable RootBeanDefinition mbd) {

        String currentlyCreatedBean = this.currentlyCreatedBean.get();
        if(currentlyCreatedBean != null){
            registerDependentBean(beanName, currentlyCreatedBean);
        }

        return super.getObjectForBeanInstance(beanInstance, name, beanName, mbd);
    }

    /**
     * Determine candidate constructors to use for the given bean, checking all registered
     * {@link SmartInstantiationAwareBeanPostProcessor SmartInstantiationAwareBeanPostProcessors}.
     * @param beanClass the raw class of the bean
     * @param beanName  the name of the bean
     * @return the candidate constructors, or {@code null} if none specified
     * @throws org.springframework.beans.BeansException in case of errors
     * @see org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors
     */
    @Nullable
    protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass,
                                                                           String beanName) throws BeansException {

        if(beanClass != null && hasInstantiationAwareBeanPostProcessors()){
            for(BeanPostProcessor bp: getBeanPostProcessors()){
                if(bp instanceof SmartInstantiationAwareBeanPostProcessor){
                    SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor)bp;
                    Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
                    if(ctors != null){
                        return ctors;
                    }
                }
            }
        }
        return null;
    }

    /**
     * Instantiate the given bean using its default constructor.
     * @param beanName the name of the bean
     * @param mbd      the bean definition for the bean
     * @return a BeanWrapper for the new instance
     */
    protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
        try{
            Object beanInstance;
            final BeanFactory parent = this;
            if(System.getSecurityManager() != null){
                beanInstance =
                        AccessController.doPrivileged((PrivilegedAction<Object>)() -> getInstantiationStrategy().instantiate(mbd, beanName, parent), getAccessControlContext());
            }else{
                //使用指定的策略模式来初始化实例，默认用的是SimpleInstantiationStrategy的cglib方法
                beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
            }
            BeanWrapper bw = new BeanWrapperImpl(beanInstance);
            initBeanWrapper(bw);
            return bw;
        }catch(Throwable ex){
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
        }
    }

    /**
     * Instantiate the bean using a named factory method. The method may be static, if the
     * mbd parameter specifies a class, rather than a factoryBean, or an instance variable
     * on a factory object itself configured using Dependency Injection.
     * @param beanName     the name of the bean
     * @param mbd          the bean definition for the bean
     * @param explicitArgs argument values passed in programmatically via the getBean method,
     *                     or {@code null} if none (-> use constructor argument values from bean definition)
     * @return a BeanWrapper for the new instance
     * @see #getBean(String, Object[])
     */
    protected BeanWrapper instantiateUsingFactoryMethod(String beanName, RootBeanDefinition mbd,
                                                        @Nullable Object[] explicitArgs) {

        return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
    }

    /**
     * "autowire constructor" (with constructor arguments by type) behavior.
     * Also applied if explicit constructor argument values are specified,
     * matching all remaining arguments with beans from the bean factory.
     * <p>This corresponds to constructor injection: In this mode, a Spring
     * bean factory is able to host components that expect constructor-based
     * dependency resolution.
     * @param beanName     the name of the bean
     * @param mbd          the bean definition for the bean
     * @param ctors        the chosen candidate constructors
     * @param explicitArgs argument values passed in programmatically via the getBean method,
     *                     or {@code null} if none (-> use constructor argument values from bean definition)
     * @return a BeanWrapper for the new instance
     */
    protected BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
                                              @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) {

        return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
    }

    /**
     * Populate the bean instance in the given BeanWrapper with the property values
     * from the bean definition.
     * @param beanName the name of the bean
     * @param mbd      the bean definition for the bean
     * @param bw       the BeanWrapper with bean instance
     */
    @SuppressWarnings("deprecation")  // for postProcessPropertyValues
    protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
        if(bw == null){
            if(mbd.hasPropertyValues()){
                throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values"
                        + " to null instance");
            }else{
                // Skip property population phase for null instance.
                return;
            }
        }

        // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
        // state of the bean before properties are set. This can be used, for example,
        // to support styles of field injection.
        // 给InstantiationAwareBeanPostProcessors最后一次机会在属性注入前修改Bean的属性值，也可以控制是否继续填充Bean
        // 具体通过调用postProcessAfterInstantiation方法，如果调用返回false,表示不必继续进行依赖注入，直接返回
        // 主要是让用户可以自定义属性注入。比如用户实现一个 InstantiationAwareBeanPostProcessor 类型的后置处理器，
        // 并通过 postProcessAfterInstantiation 方法向 bean 的成员变量注入自定义的信息。
        boolean continueWithPropertyPopulation = true;

        if(!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()){
            for(BeanPostProcessor bp: getBeanPostProcessors()){
                if(bp instanceof InstantiationAwareBeanPostProcessor){
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
                    if(!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)){
                        continueWithPropertyPopulation = false;
                        break;
                    }
                }
            }
        }
        //如果上面设置 continueWithPropertyPopulation = false，表明用户可能已经自己填充了
        // bean 的属性，不需要 Spring 帮忙填充了。此时直接返回即可
        if(!continueWithPropertyPopulation){
            return;
        }
        // pvs是一个MutablePropertyValues实例，里面实现了PropertyValues接口，
        // 提供属性的读写操作实现，同时可以通过调用构造函数实现深拷贝
        //获取BeanDefinition里面为Bean设置上的属性值
        PropertyValues pvs = (mbd.hasPropertyValues()?mbd.getPropertyValues():null);
        // 根据Bean配置的依赖注入方式完成注入，默认是0，即不走以下逻辑，所有的依赖注入都需要在xml文件中有显式的配置
        // 如果设置了相关的依赖装配方式，会遍历Bean中的属性，根据类型或名称来完成相应注入，无需额外配置
        int resolvedAutowireMode = mbd.getResolvedAutowireMode();
        if(resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE){
            MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
            // Add property values based on autowire by name if applicable.
            // 根据beanName进行autowiring自动装配处理
            // 	<bean id="boyFriend" class="com.imooc.dao.impl.BoyFriend"  autowire="byName"></bean>
            if(resolvedAutowireMode == AUTOWIRE_BY_NAME){
                autowireByName(beanName, mbd, bw, newPvs);
            }
            // Add property values based on autowire by type if applicable.
            //根据Bean的类型进行autowiring自动装配处理
            //	<bean id="boyFriend" class="com.imooc.dao.impl.BoyFriend"  autowire="byType"></bean>
            if(resolvedAutowireMode == AUTOWIRE_BY_TYPE){
                autowireByType(beanName, mbd, bw, newPvs);
            }
            pvs = newPvs;
        }
        // 容器是否注册了InstantiationAwareBeanPostProcessor
        boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
        // 是否进行依赖检查，默认为false
        boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

        PropertyDescriptor[] filteredPds = null;
        if(hasInstAwareBpps){
            if(pvs == null){
                pvs = mbd.getPropertyValues();
            }
            for(BeanPostProcessor bp: getBeanPostProcessors()){
                if(bp instanceof InstantiationAwareBeanPostProcessor){
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
                    //在这里会对@Autowired标记的属性进行依赖注入
                    PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
                    if(pvsToUse == null){
                        if(filteredPds == null){
                            filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                        }
                        // 对解析完但未设置的属性再进行处理
                        pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                        if(pvsToUse == null){
                            return;
                        }
                    }
                    pvs = pvsToUse;
                }
            }
        }
        // 依赖检查，对应depend-on属性，3.0已经弃用此属性
        if(needsDepCheck){
            // 过滤出所有需要进行依赖检查的属性编辑器
            if(filteredPds == null){
                filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            }
            checkDependencies(beanName, mbd, filteredPds, pvs);
        }

        if(pvs != null){
            //最终将属性注入到Bean的Wrapper实例里，这里的注入主要是供
            //显式配置了autowiredbyName或者ByType的属性注入，
            //针对注解来讲，由于在AutowiredAnnotationBeanPostProcessor已经完成了注入，
            //所以此处不执行
            applyPropertyValues(beanName, mbd, bw, pvs);
        }
    }

    /**
     * Fill in any missing property values with references to
     * other beans in this factory if autowire is set to "byName".
     * @param beanName the name of the bean we're wiring up.
     *                 Useful for debugging messages; not used functionally.
     * @param mbd      bean definition to update through autowiring
     * @param bw       the BeanWrapper from which we can obtain information about the bean
     * @param pvs      the PropertyValues to register wired objects with
     */
    protected void autowireByName(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw,
                                  MutablePropertyValues pvs) {
        //获取要注入的非简单类型的属性名称
        String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
        for(String propertyName: propertyNames){
            // 检测是否存在与 propertyName 相关的 bean 或 BeanDefinition。
            // 若存在，则调用 BeanFactory.getBean 方法获取 bean 实例
            if(containsBean(propertyName)){
                // 从容器中获取相应的 bean 实例
                Object bean = getBean(propertyName);
                // 将解析出的 bean 存入到属性值列表pvs中
                pvs.add(propertyName, bean);
                //注册依赖关系
                registerDependentBean(propertyName, beanName);
                if(logger.isTraceEnabled()){
                    logger.trace("Added autowiring by name from bean name '"
                            + beanName
                            + "' via property '"
                            + propertyName
                            + "' to bean named '"
                            + propertyName
                            + "'");
                }
            }else{
                if(logger.isTraceEnabled()){
                    logger.trace("Not autowiring property '"
                            + propertyName
                            + "' of bean '"
                            + beanName
                            + "' by name: no matching bean found");
                }
            }
        }
    }

    /**
     * Abstract method defining "autowire by type" (bean properties by type) behavior.
     * <p>This is like PicoContainer default, in which there must be exactly one bean
     * of the property type in the bean factory. This makes bean factories simple to
     * configure for small namespaces, but doesn't work as well as standard Spring
     * behavior for bigger applications.
     * @param beanName the name of the bean to autowire by type
     * @param mbd      the merged bean definition to update through autowiring
     * @param bw       the BeanWrapper from which we can obtain information about the bean
     * @param pvs      the PropertyValues to register wired objects with
     */
    protected void autowireByType(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw,
                                  MutablePropertyValues pvs) {
        //获取的属性类型转换器
        TypeConverter converter = getCustomTypeConverter();
        if(converter == null){
            converter = bw;
        }
        //用来存放解析的要注入的属性名
        Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
        //获取要注入的属性名称（非简单属性（8种原始类型、字符、URL等都是简单属性））
        String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
        for(String propertyName: propertyNames){
            try{
                //获取指定属性名称的属性Descriptor(Descriptor用来记载属性的getter setter type等情况)
                PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
                // Don't try autowiring by type for type Object: never makes sense,
                // even if it technically is a unsatisfied, non-simple property.
                //不对Object类型的属性进行装配注入，技术上没法实现，并且没有意义
                //即如果属性类型为 Object，则忽略，不做解析
                if(Object.class != pd.getPropertyType()){
                    //获取属性的setter方法
                    MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
                    // Do not allow eager init for type matching in case of a prioritized post-processor.
                    // 对于继承了PriorityOrdered的post-processor，不允许立即初始化(热加载)
                    boolean eager = !PriorityOrdered.class.isInstance(bw.getWrappedInstance());
                    //创建一个要被注入的依赖描述，方便提供统一的访问
                    DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
                    //根据容器的BeanDefinition解析依赖关系，返回所有要被注入的Bean实例
                    Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
                    if(autowiredArgument != null){
                        // 将解析出的 bean 存入到属性值列表pvs中
                        pvs.add(propertyName, autowiredArgument);
                    }
                    for(String autowiredBeanName: autowiredBeanNames){
                        //注册依赖关系
                        registerDependentBean(autowiredBeanName, beanName);
                        if(logger.isTraceEnabled()){
                            logger.trace("Autowiring by type from bean name '"
                                    + beanName
                                    + "' via property '"
                                    + propertyName
                                    + "' to bean named '"
                                    + autowiredBeanName
                                    + "'");
                        }
                    }
                    //清除已注入属性的记录
                    autowiredBeanNames.clear();
                }
            }catch(BeansException ex){
                throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
            }
        }
    }

    /**
     * Return an array of non-simple bean properties that are unsatisfied.
     * These are probably unsatisfied references to other beans in the
     * factory. Does not include simple properties like primitives or Strings.
     * @param mbd the merged bean definition the bean was created with
     * @param bw  the BeanWrapper the bean was created with
     * @return an array of bean property names
     * @see org.springframework.beans.BeanUtils#isSimpleProperty
     */
	/*
	 * 获取非简单类型属性的名称，且该属性未被配置在配置文件中。
	 * bean class="org.springframework.aop.framework.ProxyFactoryBean">
	 * 	<property name="target">
	 				<ref parent="accountService"/>
	 * 	</property>
	 * </bean>
	 * Spring 认为的"简单类型"属性有哪些，如下：
	 *   1. CharSequence 接口的实现类，比如 String
	 *   2. Enum
	 *   3. Date
	 *   4. URI/URL
	 *   5. Number 的继承类，比如 Integer/Long
	 *   6. byte/short/int... 等基本类型
	 *   7. Locale
	 *   8. 以上所有类型的数组形式，比如 String[]、Date[]、int[] 等等
	 *
	 * 除了要求非简单类型的属性外，还要求属性未在配置文件中配置过，也就是 pvs.contains(pd.getName()) = false。
	 */
    protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
        Set<String> result = new TreeSet<>();
        PropertyValues pvs = mbd.getPropertyValues();
        PropertyDescriptor[] pds = bw.getPropertyDescriptors();
        for(PropertyDescriptor pd: pds){
            if(pd.getWriteMethod() != null
                    && !isExcludedFromDependencyCheck(pd)
                    && !pvs.contains(pd.getName())
                    && !BeanUtils.isSimpleProperty(pd.getPropertyType())){
                result.add(pd.getName());
            }
        }
        return StringUtils.toStringArray(result);
    }

    /**
     * Extract a filtered set of PropertyDescriptors from the given BeanWrapper,
     * excluding ignored dependency types or properties defined on ignored dependency interfaces.
     * @param bw    the BeanWrapper the bean was created with
     * @param cache whether to cache filtered PropertyDescriptors for the given bean Class
     * @return the filtered PropertyDescriptors
     * @see #isExcludedFromDependencyCheck
     * @see #filterPropertyDescriptorsForDependencyCheck(org.springframework.beans.BeanWrapper)
     */
    protected PropertyDescriptor[] filterPropertyDescriptorsForDependencyCheck(BeanWrapper bw, boolean cache) {
        PropertyDescriptor[] filtered = this.filteredPropertyDescriptorsCache.get(bw.getWrappedClass());
        if(filtered == null){
            filtered = filterPropertyDescriptorsForDependencyCheck(bw);
            if(cache){
                PropertyDescriptor[] existing =
                        this.filteredPropertyDescriptorsCache.putIfAbsent(bw.getWrappedClass(), filtered);
                if(existing != null){
                    filtered = existing;
                }
            }
        }
        return filtered;
    }

    /**
     * Extract a filtered set of PropertyDescriptors from the given BeanWrapper,
     * excluding ignored dependency types or properties defined on ignored dependency interfaces.
     * @param bw the BeanWrapper the bean was created with
     * @return the filtered PropertyDescriptors
     * @see #isExcludedFromDependencyCheck
     */
    protected PropertyDescriptor[] filterPropertyDescriptorsForDependencyCheck(BeanWrapper bw) {
        List<PropertyDescriptor> pds = new ArrayList<>(Arrays.asList(bw.getPropertyDescriptors()));
        pds.removeIf(this::isExcludedFromDependencyCheck);
        return pds.toArray(new PropertyDescriptor[0]);
    }

    /**
     * Determine whether the given bean property is excluded from dependency checks.
     * <p>This implementation excludes properties defined by CGLIB and
     * properties whose type matches an ignored dependency type or which
     * are defined by an ignored dependency interface.
     * @param pd the PropertyDescriptor of the bean property
     * @return whether the bean property is excluded
     * @see #ignoreDependencyType(Class)
     * @see #ignoreDependencyInterface(Class)
     */
    protected boolean isExcludedFromDependencyCheck(PropertyDescriptor pd) {
        return (AutowireUtils.isExcludedFromDependencyCheck(pd)
                || this.ignoredDependencyTypes.contains(pd.getPropertyType())
                || AutowireUtils.isSetterDefinedInInterface(pd, this.ignoredDependencyInterfaces));
    }

    /**
     * Perform a dependency check that all properties exposed have been set,
     * if desired. Dependency checks can be objects (collaborating beans),
     * simple (primitives and String), or all (both).
     * @param beanName the name of the bean
     * @param mbd      the merged bean definition the bean was created with
     * @param pds      the relevant property descriptors for the target bean
     * @param pvs      the property values to be applied to the bean
     * @see #isExcludedFromDependencyCheck(java.beans.PropertyDescriptor)
     */
    protected void checkDependencies(String beanName, AbstractBeanDefinition mbd, PropertyDescriptor[] pds,
                                     @Nullable PropertyValues pvs) throws UnsatisfiedDependencyException {

        int dependencyCheck = mbd.getDependencyCheck();
        for(PropertyDescriptor pd: pds){
            if(pd.getWriteMethod() != null && (pvs == null || !pvs.contains(pd.getName()))){
                boolean isSimple = BeanUtils.isSimpleProperty(pd.getPropertyType());
                boolean unsatisfied = (dependencyCheck == AbstractBeanDefinition.DEPENDENCY_CHECK_ALL) || (isSimple
                        && dependencyCheck == AbstractBeanDefinition.DEPENDENCY_CHECK_SIMPLE) || (!isSimple
                        && dependencyCheck == AbstractBeanDefinition.DEPENDENCY_CHECK_OBJECTS);
                if(unsatisfied){
                    throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, pd.getName(),
                            "Set this property value or disable dependency checking for this bean.");
                }
            }
        }
    }

    /**
     * Apply the given property values, resolving any runtime references
     * to other beans in this bean factory. Must use deep copy, so we
     * don't permanently modify this property.
     * @param beanName the bean name passed for better exception information
     * @param mbd      the merged bean definition
     * @param bw       the BeanWrapper wrapping the target object
     * @param pvs      the new property values
     */
    protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
        if(pvs.isEmpty()){
            return;
        }

        if(System.getSecurityManager() != null && bw instanceof BeanWrapperImpl){
            //设置安全上下文，JDK安全机制
            ((BeanWrapperImpl)bw).setSecurityContext(getAccessControlContext());
        }

        MutablePropertyValues mpvs = null;
        List<PropertyValue> original;

        if(pvs instanceof MutablePropertyValues){
            mpvs = (MutablePropertyValues)pvs;
            if(mpvs.isConverted()){
                // Shortcut: use the pre-converted values as-is.
                //若属性值已经转换了，则直接赋值
                try{
                    bw.setPropertyValues(mpvs);
                    return;
                }catch(BeansException ex){
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property "
                            + "values", ex);
                }
            }
            //若没有被转换，先将没转换前的原始类型值给记录下来
            original = mpvs.getPropertyValueList();
        }else{
            // 如果 pvs 不是 MutablePropertyValues 类型，则直接使用原始类型
            original = Arrays.asList(pvs.getPropertyValues());
        }
        //获取用户的自定义类型转换
        TypeConverter converter = getCustomTypeConverter();
        if(converter == null){
            converter = bw;
        }
        //创建一个Bean定义属性值解析器，将BeanDefinition中的属性值解析为Bean实例对象的实际值
        BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);

        // Create a deep copy, resolving any references for values.
        // 为属性需要解析的值创建一个副本，将副本的数据注入Bean实例
        List<PropertyValue> deepCopy = new ArrayList<>(original.size());
        boolean resolveNecessary = false;
        for(PropertyValue pv: original){
            //不需要转换的属性值直接添加
            if(pv.isConverted()){
                deepCopy.add(pv);
            }else{
                String propertyName = pv.getName();
                //保留转换前的属性值
                Object originalValue = pv.getValue();
                //如果是被Autowired标记的实例，则把Bean里面关于set此属性的方法给记录下来，包装成DependencyDescriptor
                if(originalValue == AutowiredPropertyMarker.INSTANCE){
                    Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod();
                    if(writeMethod == null){
                        throw new IllegalArgumentException("Autowire marker for property without write method: " + pv);
                    }
                    originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true);
                }
                //转换属性值，如将引用转换为容器中实例化的对象引用
                Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
                Object convertedValue = resolvedValue;
                //属性值是否可以转换
                boolean convertible = bw.isWritableProperty(propertyName)
                        && !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
                if(convertible){
                    //使用用户自定义的类型转换器转换属性值
                    convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
                }
                // Possibly store converted value in merged bean definition,
                // in order to avoid re-conversion for every created bean instance.
                //存储转换后的属性值，避免每次属性注入时的转换工作
                if(resolvedValue == originalValue){
                    if(convertible){
                        pv.setConvertedValue(convertedValue);
                    }
                    deepCopy.add(pv);
                }else if(convertible
                        && originalValue instanceof TypedStringValue
                        && !((TypedStringValue)originalValue).isDynamic()
                        && !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))){
                    pv.setConvertedValue(convertedValue);
                    deepCopy.add(pv);
                }else{
                    resolveNecessary = true;
                    deepCopy.add(new PropertyValue(pv, convertedValue));
                }
            }
        }
        if(mpvs != null && !resolveNecessary){
            //标记属性已经转换过
            mpvs.setConverted();
        }

        // Set our (possibly massaged) deep copy.
        try{
            //进行属性的依赖注入
            bw.setPropertyValues(new MutablePropertyValues(deepCopy));
        }catch(BeansException ex){
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property values",
                    ex);
        }
    }

    /**
     * Convert the given value for the specified target property.
     */
    @Nullable
    private Object convertForProperty(@Nullable Object value, String propertyName, BeanWrapper bw,
                                      TypeConverter converter) {

        if(converter instanceof BeanWrapperImpl){
            return ((BeanWrapperImpl)converter).convertForProperty(value, propertyName);
        }else{
            PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
            MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
            return converter.convertIfNecessary(value, pd.getPropertyType(), methodParam);
        }
    }

    /**
     * Initialize the given bean instance, applying factory callbacks
     * as well as init methods and bean post processors.
     * <p>Called from {@link #createBean} for traditionally defined beans,
     * and from {@link #initializeBean} for existing bean instances.
     * @param beanName the bean name in the factory (for debugging purposes)
     * @param bean     the new bean instance we may need to initialize
     * @param mbd      the bean definition that the bean was created with
     *                 (can also be {@code null}, if given an existing bean instance)
     * @return the initialized bean instance (potentially wrapped)
     * @see BeanNameAware
     * @see BeanClassLoaderAware
     * @see BeanFactoryAware
     * @see #applyBeanPostProcessorsBeforeInitialization
     * @see #invokeInitMethods
     * @see #applyBeanPostProcessorsAfterInitialization
     */
    protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
        if(System.getSecurityManager() != null){
            AccessController.doPrivileged((PrivilegedAction<Object>)() -> {
                invokeAwareMethods(beanName, bean);
                return null;
            }, getAccessControlContext());
        }else{
            invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if(mbd == null || !mbd.isSynthetic()){
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try{
            invokeInitMethods(beanName, wrappedBean, mbd);
        }catch(Throwable ex){
            throw new BeanCreationException((mbd
                                                     != null?mbd.getResourceDescription():null), beanName,
                    "Invocation of init method failed", ex);
        }
        if(mbd == null || !mbd.isSynthetic()){
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

        return wrappedBean;
    }

    private void invokeAwareMethods(final String beanName, final Object bean) {
        if(bean instanceof Aware){
            if(bean instanceof BeanNameAware){
                ((BeanNameAware)bean).setBeanName(beanName);
            }
            if(bean instanceof BeanClassLoaderAware){
                ClassLoader bcl = getBeanClassLoader();
                if(bcl != null){
                    ((BeanClassLoaderAware)bean).setBeanClassLoader(bcl);
                }
            }
            if(bean instanceof BeanFactoryAware){
                ((BeanFactoryAware)bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
            }
        }
    }

    /**
     * Give a bean a chance to react now all its properties are set,
     * and a chance to know about its owning bean factory (this object).
     * This means checking whether the bean implements InitializingBean or defines
     * a custom init method, and invoking the necessary callback(s) if it does.
     * @param beanName the bean name in the factory (for debugging purposes)
     * @param bean     the new bean instance we may need to initialize
     * @param mbd      the merged bean definition that the bean was created with
     *                 (can also be {@code null}, if given an existing bean instance)
     * @throws Throwable if thrown by init methods or by the invocation process
     * @see #invokeCustomInitMethod
     */
    protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd) throws Throwable {
        //如果当前bean是 InitializingBean类型的&&afterPropertiesSet这个方法没有注册为外部管理的初始化方法
        //就回调afterPropertiesSet方法
        boolean isInitializingBean = (bean instanceof InitializingBean);
        if(isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))){
            if(logger.isTraceEnabled()){
                logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
            }
            if(System.getSecurityManager() != null){
                try{
                    AccessController.doPrivileged((PrivilegedExceptionAction<Object>)() -> {
                        ((InitializingBean)bean).afterPropertiesSet();
                        return null;
                    }, getAccessControlContext());
                }catch(PrivilegedActionException pae){
                    throw pae.getException();
                }
            }else{
                ((InitializingBean)bean).afterPropertiesSet();
            }
        }

        if(mbd != null && bean.getClass() != NullBean.class){
            String initMethodName = mbd.getInitMethodName();
            //如果设置了initMethod方法的话也会执行用户配置的初始话方法
            //并且这个类不是 InitializingBean类型和不是afterPropertiesSet方法 ；
            //才能执行用户配置的方法
            //样例<bean id="person" class="com.imooc.Person"  init-method="init" destroy-method="destory"/>
            if(StringUtils.hasLength(initMethodName)
                    && !(isInitializingBean
                    && "afterPropertiesSet".equals(initMethodName))
                    && !mbd.isExternallyManagedInitMethod(initMethodName)){
                invokeCustomInitMethod(beanName, bean, mbd);
            }
        }
    }

    /**
     * Invoke the specified custom init method on the given bean.
     * Called by invokeInitMethods.
     * <p>Can be overridden in subclasses for custom resolution of init
     * methods with arguments.
     * @see #invokeInitMethods
     */
    protected void invokeCustomInitMethod(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {

        String initMethodName = mbd.getInitMethodName();
        Assert.state(initMethodName != null, "No init method set");
        Method initMethod = (mbd.isNonPublicAccessAllowed()?BeanUtils.findMethod(bean.getClass(), initMethodName):
                             ClassUtils
                .getMethodIfAvailable(bean.getClass(), initMethodName));

        if(initMethod == null){
            if(mbd.isEnforceInitMethod()){
                throw new BeanDefinitionValidationException("Could not find an init method named '"
                        + initMethodName
                        + "' on bean with name '"
                        + beanName
                        + "'");
            }else{
                if(logger.isTraceEnabled()){
                    logger.trace("No default init method named '"
                            + initMethodName
                            + "' found on bean with name '"
                            + beanName
                            + "'");
                }
                // Ignore non-existent default lifecycle methods.
                return;
            }
        }

        if(logger.isTraceEnabled()){
            logger.trace("Invoking init method  '" + initMethodName + "' on bean with name '" + beanName + "'");
        }
        Method methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(initMethod);

        if(System.getSecurityManager() != null){
            AccessController.doPrivileged((PrivilegedAction<Object>)() -> {
                ReflectionUtils.makeAccessible(methodToInvoke);
                return null;
            });
            try{
                AccessController.doPrivileged((PrivilegedExceptionAction<Object>)() -> methodToInvoke.invoke(bean),
                        getAccessControlContext());
            }catch(PrivilegedActionException pae){
                InvocationTargetException ex = (InvocationTargetException)pae.getException();
                throw ex.getTargetException();
            }
        }else{
            try{
                ReflectionUtils.makeAccessible(methodToInvoke);
                methodToInvoke.invoke(bean);
            }catch(InvocationTargetException ex){
                throw ex.getTargetException();
            }
        }
    }

    /**
     * Applies the {@code postProcessAfterInitialization} callback of all
     * registered BeanPostProcessors, giving them a chance to post-process the
     * object obtained from FactoryBeans (for example, to auto-proxy them).
     * @see #applyBeanPostProcessorsAfterInitialization
     */
    @Override
    protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
        return applyBeanPostProcessorsAfterInitialization(object, beanName);
    }

    /**
     * Overridden to clear FactoryBean instance cache as well.
     */
    @Override
    protected void removeSingleton(String beanName) {
        synchronized(getSingletonMutex()){
            super.removeSingleton(beanName);
            this.factoryBeanInstanceCache.remove(beanName);
        }
    }

    /**
     * Overridden to clear FactoryBean instance cache as well.
     */
    @Override
    protected void clearSingletonCache() {
        synchronized(getSingletonMutex()){
            super.clearSingletonCache();
            this.factoryBeanInstanceCache.clear();
        }
    }

    /**
     * Expose the logger to collaborating delegates.
     * @since 5.0.7
     */
    Log getLogger() {
        return logger;
    }

    /**
     * Special DependencyDescriptor variant for Spring's good old autowire="byType" mode.
     * Always optional; never considering the parameter name for choosing a primary candidate.
     */
    @SuppressWarnings("serial")
    private static class AutowireByTypeDependencyDescriptor extends DependencyDescriptor {

        public AutowireByTypeDependencyDescriptor(MethodParameter methodParameter, boolean eager) {
            super(methodParameter, false, eager);
        }

        @Override
        public String getDependencyName() {
            return null;
        }

    }

    /**
     * {@link MethodCallback} used to find {@link FactoryBean} type information.
     */
    private static class FactoryBeanMethodTypeFinder implements MethodCallback {

        private final String factoryMethodName;

        private ResolvableType result = ResolvableType.NONE;

        FactoryBeanMethodTypeFinder(String factoryMethodName) {
            this.factoryMethodName = factoryMethodName;
        }

        @Override
        public void doWith(Method method) throws IllegalArgumentException {
            if(isFactoryBeanMethod(method)){
                ResolvableType returnType = ResolvableType.forMethodReturnType(method);
                ResolvableType candidate = returnType.as(FactoryBean.class).getGeneric();
                if(this.result == ResolvableType.NONE){
                    this.result = candidate;
                }else{
                    Class<?> resolvedResult = this.result.resolve();
                    Class<?> commonAncestor = ClassUtils.determineCommonAncestor(candidate.resolve(), resolvedResult);
                    if(!ObjectUtils.nullSafeEquals(resolvedResult, commonAncestor)){
                        this.result = ResolvableType.forClass(commonAncestor);
                    }
                }
            }
        }

        private boolean isFactoryBeanMethod(Method method) {
            return (method.getName().equals(this.factoryMethodName)
                    && FactoryBean.class.isAssignableFrom(method.getReturnType()));
        }

        ResolvableType getResult() {
            Class<?> resolved = this.result.resolve();
            boolean foundResult = resolved != null && resolved != Object.class;
            return (foundResult?this.result:ResolvableType.NONE);
        }

    }

}
